﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Security.Cryptography;
using System.Windows;

namespace Cerebrata.CloudStorage.Utilities.FileUploader
{
    public static class TableStorageRestHelper
    {

       private static string KeyType = "SharedKey";
       private static string AccountName = String.Empty;
       private static string contentType = "application/atom+xml";
       private static string SharedKey = String.Empty;

        

       
        
        internal static bool UploadEntity(string Accountname, string AccountKey, string TableName, DateTime RequestDate, string RowXML)
        {
            AccountName = Accountname;
            SharedKey = AccountKey;
            string urlMask = App.EndPoint;
            string endPoint = string.Format(urlMask, Accountname);
            string contentType = "application/atom+xml";
            string ContentMD5 = string.Empty;
            string AuthorizationValue = string.Empty;
            string SignedValue = string.Empty;
            string AuthorizationHeader = string.Empty;
            string HttpMethod = "POST";
            string ReturnBody = string.Empty;
            string RequestBody = string.Empty;
            string canonicalResource = string.Format("/{0}/{1}", Accountname, TableName);
            string requestUrl = string.Format("{0}/{1}?", endPoint, TableName);
           
            RequestBody = RowXML;// string.Format(EntityData[i], "{0:R}", RequestDate);
            ContentMD5 = MD5(RequestBody);
            AuthorizationHeader = CreateSharedKeyAuth(HttpMethod, canonicalResource, ContentMD5, RequestDate);
            WebRequest req = null;
            WebResponse resp = null;
            try
            {
                req = WebRequest.Create(requestUrl);
                req.Headers.Add("content-md5", ContentMD5);
                req.Headers.Add("x-ms-date", string.Format("{0:R}", RequestDate));
                req.Headers.Add("authorization", AuthorizationHeader);
                req.ContentType = contentType;
                req.ContentLength = Encoding.UTF8.GetBytes(RequestBody).Length;
                req.Method = HttpMethod;

                

                using (StreamWriter sw = new StreamWriter(req.GetRequestStream()))
                {
                    sw.Write(RequestBody);
                    sw.Close();
                }
                resp = req.GetResponse();

                
                return true;

            }
            catch (Exception e)
            {
              return false;
            }
            finally
            {
                req = null;
                if (resp != null)
                {
                    resp.Close();
                }
                resp = null;
            }

        }

        static private string CreateSharedKeyAuth(string method, string resource, string contentMD5, DateTime requestDate)
        {


            try
            {
                string rtn = string.Empty;
                string fmtHeader = "{0} {1}:{2}";
                string fmtStringToSign = "{0}\n{1}\n{2}\n{3:R}\n{4}";

                string authValue = string.Format(fmtStringToSign, method, contentMD5, contentType, requestDate, resource);
                string sigValue = MacSha(authValue, Convert.FromBase64String(SharedKey));
                rtn = string.Format(fmtHeader, KeyType, AccountName, sigValue);

                return rtn;
            }
            catch (Exception)
            {
               return String.Empty;
            }
        
        }

        // hashing helper
        static string MacSha(string canonicalizedString, byte[] key)
        {
            byte[] dataToMAC = System.Text.Encoding.UTF8.GetBytes(canonicalizedString);

            using (HMACSHA256 hmacsha1 = new HMACSHA256(key))
            {
                return System.Convert.ToBase64String(hmacsha1.ComputeHash(dataToMAC));
            }
        }
        static string MD5(string data)
        {
            return MD5(data, false);
        }
        static string MD5(string data, bool removeTail)
        {
            string rtn = Convert.ToBase64String(new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(System.Text.Encoding.Default.GetBytes(data)));
            if (removeTail)
                return rtn.Replace("=", "");
            else
                return rtn;
        }

     

    }
}
